use std::io::Write;

use log::{debug, info};

use crate::IInstr;

#[derive(Default)]
pub struct CurrentData {
    pub avgCurr: f64,
    pub highCuur: f64,
    pub lowCurr: f64,
    pub maxCurr: f64,
    pub minCurr: f64,
}
impl CurrentData {
    pub fn new() -> Self {
        Self {
            ..Default::default()
        }
    }
    pub fn to_tb(&self)->String{
        format!("{},{},{},{},{}",self.avgCurr,self.maxCurr,self.minCurr,self.highCuur,self.lowCurr)
    }
}
impl std::fmt::Display for CurrentData {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "avg:{}, max:{}, min:{} ,high:{} ,low:{}",  self.avgCurr, self.maxCurr, self.minCurr, self.highCuur, self.lowCurr)
    }
}


pub struct P66319D{
    instr: visa_rs::Instrument,
    pub datafile:Option<std::fs::File>,
}

impl P66319D {
    pub fn new(instr:visa_rs::Instrument)->Self{
        Self { instr ,datafile:None}
    }
    pub fn m_init(&mut self) -> std::io::Result<()> {
        self.instr.m_send("*RST; *OPC?")
    }
    /// channel 1|2 ,volt v
    pub fn m_set_volt(&mut self, channel: u64, volt: f64)->std::io::Result<()> {
        self.instr.m_send(&format!("SOUR{}:VOLT {:.2}", channel, volt))
    }
    pub fn m_set_test_accur(&mut self, accur: &str)->std::io::Result<()> {
            match accur {
                "100.us/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 38;OFFS:POIN 0")
                }
                "200.us/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 76;OFFS:POIN 0")
                }
                "500.us/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 192;OFFS:POIN 0")
                }
                "1.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 384;OFFS:POIN 0")
                }
                "2.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 769;OFFS:POIN 0")
                }
                "5.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 1923;OFFS:POIN 0")
                }
                "10.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 1.56E-005;POIN 3846;OFFS:POIN 0")
                }
                "20.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 3.12E-005;POIN 3846;OFFS:POIN 0")
                }
                "50.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 7.8E-005;POIN 3846;OFFS:POIN 0")
                }
                "100.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 0.000156;POIN 3846;OFFS:POIN 0")
                }
                "200.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 0.0002964;POIN 4048;OFFS:POIN 0")
                }
                "500.ms/div" => {
                    self.instr.m_send("SENS:SWE:TINT 0.0007332;POIN 4091;OFFS:POIN 0")
                }
                "1.s/div" => {
                    self.instr.m_send("SENS:SWE:TINT 0.0014664;POIN 4091;OFFS:POIN 0")
                }
                "2.s/div" => {
                    self.instr.m_send("SENS:SWE:TINT 0.0029328;POIN 4091;OFFS:POIN 0")
                }
                "4.s/div" => {
                    self.instr.m_send("SENS:SWE:TINT 0.0058656;POIN 4091;OFFS:POIN 0")
                }
    
                _ => {Err(std::io::Error::from_raw_os_error(233))}
            }
    }
    
    pub fn m_measure_current(&mut self) -> Option<CurrentData> {
        let mut curdata = CurrentData::new();
        self.read_esr_state();
        let ss = self.instr.m_query("MEAS:ARR:CURR?")?;
        let mut data = Vec::new();
        debug!("{ss}");
        if let Some(dfile) = &mut self.datafile{
            dfile.write(ss.as_bytes());
        }
        for idx in ss.trim().split(","){
            match idx.parse::<f64>(){
                Ok(vl) => {
                    data.push(vl);
                },
                Err(_) => {},
            }
        }
        
        debug!("count:{}",data.len());
        debug!("avgcurr:{}",data.iter().sum::<f64>()/data.len() as f64);
        
        self.read_esr_state();
        let ss = self.instr.m_query("FETC:CURR?")?;
        let ss_v = ss.trim().parse::<f64>().ok()?;
        curdata.avgCurr = ss_v;
        self.read_esr_state();
        let ss = self.instr.m_query("FETC:CURR:MAX?")?;
        let ss_v = ss.trim().parse::<f64>().ok()?;
        curdata.maxCurr = ss_v;
        self.read_esr_state();
        let ss = self.instr.m_query("FETC:CURR:MIN?")?;
        let ss_v = ss.trim().parse::<f64>().ok()?;
        curdata.minCurr = ss_v;
        self.read_esr_state();
        let ss = self.instr.m_query("FETC:CURR:HIGH?")?;
        let ss_v = ss.trim().parse::<f64>().ok()?;
        curdata.highCuur = ss_v;
        self.read_esr_state();
        let ss = self.instr.m_query("FETC:CURR:LOW?")?;
        let ss_v = ss.trim().parse::<f64>().ok()?;
        curdata.lowCurr = ss_v;
        self.read_esr_state();
            
        Some(curdata)
    }
    fn read_esr_state(&mut self) {
        loop {
            if let Some(ss) = self.instr.m_query("*ESR?") {
                if let Some(_) = ss.find("+0") {
                    break;
                }
            }
        }
    }
}
